﻿using System;
using System.Collections.Generic;
using System.ServiceModel.DomainServices.Client;

namespace SL.MVVMS.RIA
{
    /// <summary>
    /// Simple LoadOperation batch manager
    /// Interpreted from Scott McCraw
    /// Original Article: http://blogs.msdn.com/b/smccraw/archive/2009/07/15/a-net-ria-services-data-load-batch-manager.aspx
    /// </summary>
    /// <remarks>
    /// This class allows you to start multiple load operations in parallel and still received a single
    /// 'complete' action callback once all work is done. Load operation failures are also aggregated
    /// and will be made available as part of the completion action callback.
    /// </remarks>
    [Obsolete("Please use Composition instead of Loading Batches")]
    public class DomainContextLoadBatch
    {
        private List<OperationBase> _batchOperations = new List<OperationBase>();
        private List<OperationBase> _failedOperations = new List<OperationBase>();
        private Action<DomainContextLoadBatch> _completeAction;
        private volatile bool _canComplete = false;

        public bool CanComplete
        {
            get { return _canComplete; }
            set 
            { 
                _canComplete = value;
                CheckForComplete();
            }
        }

        /// <summary>
        /// Expose the count of failed operations
        /// </summary>
        public int FailedOperationCount { get { return _failedOperations.Count; } }

        /// <summary>
        /// Expose an enumerator for all of the failed operations
        /// </summary>
        public IEnumerable<OperationBase> FailedOperations { get { return _failedOperations; } }

        /// <summary>
        /// Public constructor
        /// </summary>
        /// <param name="completeAction"></param>
        public DomainContextLoadBatch(Action<DomainContextLoadBatch> completeAction)
        {
            this._completeAction = completeAction;
        }

        /// <summary>
        /// Used to add an operation to the batch
        /// </summary>
        /// <param name="loadOperation"></param>
        public void Add(OperationBase loadOperation)
        {
            loadOperation.Completed += new EventHandler(loadOperation_Completed);
            _batchOperations.Add(loadOperation);
        }

        /// <summary>
        /// Processes each operation as it completes and checks for errors
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void loadOperation_Completed(object sender, EventArgs e)
        {
            OperationBase loadOperation = sender as OperationBase;
            _batchOperations.Remove(loadOperation);
            loadOperation.Completed -= new EventHandler(loadOperation_Completed);

            if (loadOperation.Error != null)
                _failedOperations.Add(loadOperation);

            CheckForComplete();
        }

        /// <summary>
        /// Called to check for all operations being complete and to fire our completed action
        /// </summary>
        void CheckForComplete()
        {
            if (_batchOperations.Count > 0 |
                _canComplete == false)
                return;

            _completeAction(this);
            _completeAction = null;
        }
    }
}
